home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
program
/
tjgold.zip
/
INSTALL.001
/
GOLDLIST.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1995-07-12
|
92KB
|
3,120 lines
{--------------------------------------------------------------------------}
{ Product: TechnoJock's Turbo Toolkit }
{ Version: GOLD }
{ Build: 1.01 }
{ }
{ Copyright 1986-1995 TechnoJock Software, Inc. }
{ All Rights Reserved }
{ Restricted by License }
{--------------------------------------------------------------------------}
{************************}
{** Unit: GOLDLIST **}
{************************}
{++++++++++++++++++++++++++++++} unit GOLDLIST; {++++++++++++++++++++++++++++}
{$I GOLDFLAG.INC}
{$IFNDEF GOLDLIST}
{$DEFINE GOLDLIST}
{$ENDIF}
{++++++++++++++++++++++++++++++++} INTERFACE {+++++++++++++++++++++++++++++++}
uses DOS, CRT, GoldTint, GoldHard, GoldFast, GoldWin, GoldKey,
GoldIO, GoldLink, GoldStr, GoldMisc;
const
FirstListCol = ListHi1;
LastListCol = ListIcons;
ListMaxHeaders = 4; {change as necessary}
ListMaxFooters = 4; {change as necessary}
type
ListCfgPtr = ^ListCfg;
ListGetStrFunc = function(P:pointer; Element,Start,Finish: longint): string;
ListGetBitFunc = function(P:pointer; Pick:longint;BitPos:byte): boolean;
ListSetBitFunc = procedure(P:pointer; Pick:longint;BitPos:byte;On:boolean);
ListHindHook = procedure(ListDetails:ListCfgPtr);
ListSelectHook = function(ListDetails:ListCfgPtr):gAction;
ListColorHook = procedure(Pick:longint; Hi:boolean; var Attr:byte);
ListCloseProc = function(ListDetails:ListCfgPtr; Handle:integer):boolean;
GridTabArray = array [1..255] of integer;
pGridTabArray = ^GridTabArray;
ListTints = array[FirstListCol..LastListCol] of byte;
ListDataSource = (SourceUnknown,SourceArray,SourceStrLL,SourceSLL,SourceDLL,SourceCustom);
ListCfg = record
DataSource: pointer;
DataType: ListDataSource;
WX1,WY1,WX2,WY2,WStyle: shortint;
LeftGap,RightGap,BotGap,TopGap: byte;
TotalNodes: longint;
ActiveNode: longint;
TopNode: longint;
AllowTagging: boolean;
AllowTwoColors: boolean;
ChangeColorsWithTags: boolean;
IODispose: boolean;
InWindow: boolean;
Browsing: boolean;
ColWidth: byte;
RealColWidth: byte;
LastColWidth: byte;
ColCount: byte;
RowCount: byte;
Col: ListTints;
GetStr: ListGetStrFunc;
GetBit: ListGetBitFunc;
SetBit: ListSetBitFunc;
CharHook: KeyPressedHook;
HindHook: ListHindHook;
SelectHook: ListSelectHook;
ColorHook: ListColorHook;
StrLength: byte; {length of string element when editing an array}
LastKey: word;
LastAction: gAction;
{header/footer related}
Headers: array[1..ListMaxHeaders] of ^string;
ScrollHeader: boolean;
Footers: array[1..ListMaxFooters] of ^string;
ScrollFooter: boolean;
{Grid-specific vars}
StartingCol: integer;
LastCol: integer;
ColumnLock: byte;
RowLock: byte;
WriteHeadingsHook: ListHindHook;
TabsArrayPtr: pGridTabArray;
TabsArrayPos: integer;
TabsArrayDim: integer;
{internal}
X1,Y1,X2,Y2: byte; {dimensions of list (including headings)}
{desk - internal}
DeskListCloseCallBack: ListCloseProc;
end; { ListCfg }
DeskBrowseFileInfo = record {attached to a window's UserData}
Cfg: ListCfg;
DataList: DoubleLL;
end; { DeskBrowseFileInfo }
ListSet = record
LastEcode: integer;
ListLeft: string[1];
ListRight: string[1];
ListTag: string[1];
GridLeft: string[1];
GridRight: string[1];
GridTag: string[1];
ToggleKey: word;
TagKey: word;
UnTagKey: word;
TagAllKey: word;
UnTagAllKey: word;
WinStyle:byte;
WX1: byte; {default dimensions of list window}
WY1: byte;
WX2: byte;
WY2: byte;
WrapWinType: WinType;
LastActiveItem:longint;
EMsgFunc: ErrMsgFunc;
end; {List Set}
{Misc}
function LastListError: integer;
{generic list managment}
procedure InitListCFG(var ListDetails: ListCfg);
{hooks}
procedure ListAssignHindHook(var ListDetails: ListCfg; Proc:ListHindHook);
procedure ListAssignCharHook(var ListDetails: ListCfg; Proc:KeyPressedHook);
procedure ListAssignSelectHook(var ListDetails: ListCfg; Proc:ListSelectHook);
procedure ListAssignColorHook(var ListDetails: ListCfg; Proc:ListColorHook);
procedure ListRemoveHindHook(var ListDetails: ListCfg);
procedure ListRemoveCharHook(var ListDetails: ListCfg);
procedure ListRemoveSelectHook(var ListDetails: ListCfg);
procedure ListRemoveColorHook(var ListDetails: ListCfg);
{heading management}
procedure ListAssignHeader(var ListDetails: ListCfg; Line:byte; var Heading:string);
procedure ListAssignFooter(var ListDetails: ListCfg; Line:byte; var Footnote:string);
procedure ListRemoveHeader(var ListDetails: ListCfg; Line:byte);
procedure ListRemoveFooter(var ListDetails: ListCfg; Line:byte);
procedure ListScrollHeader(var ListDetails: ListCfg; On:boolean);
procedure ListScrollFooter(var ListDetails: ListCfg; On:boolean);
{general configuration}
procedure ListSetTagging(var ListDetails: ListCfg; On:boolean);
procedure ListSetTwoColors(var ListDetails: ListCfg; On:boolean);
procedure ListSetTagColor(var ListDetails: ListCfg; On:boolean);
procedure ListSetWin(var ListDetails: ListCfg; X1,Y1,X2,Y2:integer; Style:byte);
procedure ListSetGaps(var ListDetails: ListCfg; LeftGap,RightGap,BotGap,TopGap: byte);
procedure ListSetColor(var ListDetails: ListCfg; A:TintElement;C:byte);
procedure ListSetColWidth(var ListDetails: ListCfg; Width: byte);
{assigning the information source}
procedure ListAssignArray(var ListDetails: ListCfg; var ListSource; StrLen:Byte;ArrayElements:byte);
procedure ListAssignSLL(var ListDetails: ListCfg; var TheList:SingleLL);
procedure ListAssignDLL(var ListDetails: ListCfg; var TheList:DoubleLL);
procedure ListAssignCustom(var ListDetails: ListCfg; Total:longint; Proc:ListGetStrFunc);
{browsing}
procedure RunBrowse(var ListDetails: ListCfg;Tit:StrScreen);
function LaunchBrowse(var ListDetails: ListCfg;Tit:StrScreen; CloseProc:ListCloseProc): byte;
procedure RunBrowseFile(Fname:PathStr;Tit:StrScreen);
function LaunchBrowseFile(Fname:PathStr;Tit:StrScreen): byte;
{basic list windows}
function RunListStrLL(ListSource:StringLL;Tit:StrScreen):longint;
{list display}
procedure RunList(var ListDetails: ListCfg;Tit:StrScreen);
function LaunchList(var ListDetails: ListCfg;Tit:StrScreen; CloseProc:ListCloseProc): byte;
procedure ShowList(var StrArray;StrLength:byte;TotalPicks:integer);
{Internal}
procedure NoListCharHook(var K : word;var X,Y:byte);
procedure NoListHindHook(ListDetails:ListCfgPtr);
procedure NoListColorHook(Pick:longint;Hi:boolean; var Attr:byte);
procedure RefreshHeadFoot(var ListDetails: ListCfg);
procedure RecalcListDimensions(var ListDetails: ListCfg);
procedure BrowseRefresh(var ListDetails: ListCfg);
procedure BrowseProcessKey(var ListDetails: ListCfg;var K:word;X,Y:byte; MakeLocal: boolean);
procedure GListRefresh(var ListDetails: ListCfg; Status:gStatus);
procedure GListProcessKey(var ListDetails: ListCfg;var K:word;X,Y:byte;MakeLocal:boolean);
procedure WrapListProcessKey(var ListDetails: ListCfg;var K:word;X,Y:byte;MakeLocal:boolean);
procedure WrapListRefresh(var ListDetails: ListCfg; Status:gStatus);
procedure ToggleTagState(var ListDetails: ListCfg);
procedure SetTag(var ListDetails: ListCfg; On: boolean);
procedure SetTagAll(var ListDetails: ListCfg; On: boolean);
procedure DelayIt(L,InWin:boolean;var WaitTime:integer);
procedure SetInnerDimensions(var ListDetails: ListCfg);
function ListScrollUp(var ListDetails: ListCfg): boolean;
function ListScrollDown(var ListDetails: ListCfg): boolean;
function ListScrollPgDn(var ListDetails: ListCfg): boolean;
function ListScrollPgUp(var ListDetails: ListCfg): boolean;
function ListScrollHome(var ListDetails: ListCfg): boolean;
function ListScrollEnd(var ListDetails: ListCfg): boolean;
function ListCloseHandler(Handle: integer):boolean;
procedure ListFocusHandler(Handle: integer);
{$IFDEF TTT5}
Procedure Default_Settings;
Procedure Show_List(var StrArray;StrLength:Byte;TotalPicks:byte);
Procedure New_Show_List(var StrArray;StrLength:Byte;TotalPicks:byte);
{$ENDIF}
var
ListVars: ListSet;
LPicks: integer;
{+++++++++++++++++++++++++++++} IMPLEMENTATION {+++++++++++++++++++++++++++++}
{$IFOPT F-}
{$DEFINE FOFF}
{$F+}
{$ENDIF}
function ListEMsg(ECode:integer): string;
{}
begin
case Ecode of
0: exit;
1001 : ListEMsg := 'Unable to load file for browsing';
1002 : ListEMsg := 'Not enough memory to load entire file';
1003 : ListEMsg := 'Header/Footer out of range';
1004 : ListEMsg := 'Unable to create the browse/list window';
else
ListEMsg := 'Internal List error';
end; {case}
end; { ListEMsg }
{$IFDEF FOFF}
{$F-}
{$UNDEF FOFF}
{$ENDIF}
procedure ListSetError(ECode:integer);
{}
{$IFOPT D+}
var Msg: string;
{$ENDIF}
begin
ListVars.LastEcode := ECode;
{$IFOPT D+} {if debug active display an error message and terminate}
if Ecode <> 0 then
begin
str(Ecode,Msg);
Msg := Msg+': '+ListVars.EMsgFunc(Ecode);
SetWinIgnore(true);
if PromptCustom(' GoldList Error ',Msg,' ~I~gnore ',' ~A~bort ','',279,286,0,0, 10000) = 2 then
Halt;
end;
{$ENDIF}
end; {ListSetError}
function LastListError: integer;
{}
begin
LastListError := ListVars.LastEcode;
end; { LastListError }
{*********************}
{** Miscellaneous **}
{*********************}
procedure DelayIt(L,InWin:boolean;var WaitTime:integer);
{Used in scrolling routines such as list, ScrollField and the SpinFields}
begin
if L then
begin
if InWin then
WinDrawTop;
delay(WaitTime);
if WaitTime <> KeyVars.ScrollDelay then
WaitTime := KeyVars.ScrollDelay;
end;
end; { DelayIt }
procedure CalcColRow(var ListDetails: ListCfg);
{}
begin
with ListDetails do
begin
if (ColWidth = 0) or (ColWidth > X2-X1) then
begin
RealColWidth := X2-X1;
LastColWidth := RealColWidth;
ColCount := 1;
end
else
begin
RealColWidth := ColWidth;
ColCount := (X2-X1) div RealColWidth;
LastColWidth := (X2-X1) - ColCount * RealColWidth;
if LastColWidth = 0 then
LastColWidth := RealColWidth
else
inc(ColCount);
end;
RowCount := succ(Y2-Y1);
end;
end; {CalcColRow}
{*******************************}
{** Generic List Management **}
{*******************************}
{$IFOPT F-}
{$DEFINE FOFF}
{$F+}
{$ENDIF}
function DummyGetStr(P:pointer;Element,Start,Finish: longint): string;
{}
begin
DummyGetStr := '';
end; { DummyGetStr }
function DummyGetBit(P:pointer;Pick:longint;BitPos:byte): boolean;
{}
begin
DummyGetBit := false
end; { DummyGetBit }
procedure DummySetBit(P:pointer;Pick:longint;BitPos:byte;On:boolean);
{}
begin
end; { DummySetBit }
function ArrayGetStrFunc(P:pointer;Element,Start,Finish: longint): string;
{}
var
W : longint;
TempStr : String;
ArrayOffset: word;
begin
with ListCfg(P^) do
begin
if (Element < 1) or (Element > TotalNodes) then
TempStr := ''
else
begin
{move array string to Temp}
W := pred(Element) * succ(StrLength);
ArrayOffset := Ofs(DataSource^) + W;
move(Mem[Seg(DataSource^):ArrayOffset],TempStr,1);
move(Mem[Seg(DataSource^):succ(ArrayOffset)],TempStr[1],ord(TempStr[0]));
end;
if length(TempStr) < succ(Finish - Start) then
TempStr := PadLeft(TempStr,succ(Finish - Start),' ');
ArrayGetStrFunc := TempStr;
end;
end; { ArrayGetStrFunc }
function SLLGetStrFunc(P:pointer;Element,Start,Finish: longint): string;
{}
var Str:string;
begin
if (Start = 0) and (Finish = 0) then
SLLGetStrFunc := _SLLGetNodeStr(SingleLL(P^),_SLLNodePtr(SingleLL(P^),Element),0)
else
begin
Str := copy(_SLLGetNodeStr(SingleLL(P^),_SLLNodePtr(SingleLL(P^),Element),0),Start,succ(Finish-Start));
if length(Str) < succ(Finish - Start) then
Str := PadLeft(Str,succ(Finish - Start),' ');
SLLGetStrFunc := Str;
end;
end; { SLLGetStrFunc }
function SLLGetBitFunc(P:pointer;Pick:longint;BitPos:byte): boolean;
{}
begin
SLLGetBitFunc := SLLGetBit(_SLLNodePtr(SingleLL(P^),Pick),BitPos);
end; { SLLGetBitFunc }
procedure SLLSetBitFunc(P:pointer;Pick:longint;BitPos:byte;On:boolean);
{}
begin
_SLLSetBit(SingleLL(P^),_SLLNodePtr(SingleLL(P^),Pick),BitPos,On);
end; { SLLSetBitFunc }
function DLLGetStrFunc(P:pointer;Element,Start,Finish: longint): string;
{}
var Str:string;
begin
Str := copy(DLLGetNodeStr(DLLNodePtr(Element),0,255),Start,succ(Finish-Start));
if length(Str) < succ(Finish - Start) then
Str := PadLeft(Str,succ(Finish - Start),' ');
DLLGetStrFunc := Str;
end; { DLLGetStrFunc }
function DLLGetBitFunc(P:pointer;Pick:longint;BitPos:byte): boolean;
{}
begin
DLLGetBitFunc := DLLGetBit(DLLNodePtr(Pick),BitPos);
end; { DLLGetBitFunc }
procedure DLLSetBitFunc(P:pointer;Pick:longint;BitPos:byte;On:boolean);
{}
begin
DLLSetBit(DLLNodePtr(Pick),BitPos,On);
end; { DLLSetBitFunc }
procedure NoListCharHook(var K : word;var X,Y:byte);
{}
begin
end; {NoListCharHook}
procedure NoListHindHook(ListDetails:ListCfgPtr);
{}
begin
end; {NoListHindHook}
function ListDefaultSelectHook(ListDetails:ListCfgPtr):gAction;
{}
begin
with KeyVars do
begin
if (LastKey = 600)
or (LastKey = 27) then
ListDefaultSelectHook := Escaped
else if ((LastKey = 540) and (LastX <> 0))
or (LastKey = 13) then
ListDefaultSelectHook := Finished
else
ListDefaultSelectHook := None;
end
end; {ListDefaultSelectHook}
procedure NoListColorHook(Pick:longint;Hi:boolean; var Attr:byte);
{}
begin
end; {NoListColorHook}
{$IFDEF FOFF}
{$F-}
{$UNDEF FOFF}
{$ENDIF}
{**********************}
{** Initialization **}
{**********************}
procedure InitListCFG(var ListDetails: ListCfg);
{}
var
A: TintElement;
I: integer;
begin
fillchar(Listdetails,sizeof(Listdetails),#0);
with Listdetails do
begin
DataSource := nil;
DataType := SourceUnknown;
X1 := 1;
Y1 := 1;
X2 := 20;
Y2 := 10;
TotalNodes := 0;
ActiveNode := 0;
TopNode := 0;
AllowTagging := false;
AllowTwoColors := false;
ChangeColorsWithTags := false;
IODispose := true;
InWindow := false;
Browsing := false;
ColWidth := 0;
LastColWidth := 0;
ColCount := 1;
RowCount := 1;
for A := FirstListCol to LastListCol do
Col[A] := Tint[A];
GetStr := DummyGetStr;
GetBit := DummyGetBit;
SetBit := DummySetBit;
CharHook := NoListCharHook;
HindHook := NoListHindHook;
SelectHook := ListDefaultSelectHook;
ColorHook := NoListColorHook;
WStyle := ListVars.WinStyle;
{header/footer stuff}
for I := 1 to ListMaxHeaders do
Headers[I] := nil;
ScrollHeader := true;
for I := 1 to ListMaxFooters do
Footers[I] := nil;
ScrollFooter := true;
{Form stuff}
ColumnLock := 0;
RowLock := 0;
StartingCol := 1;
LastCol := 255;
WriteHeadingsHook := NoListHindHook;
TabsArrayPtr := nil;
TabsArrayPos := 1;
TabsArrayDim := 0;
end;
end; { InitListCFG }
procedure ListSetWin(var ListDetails: ListCfg; X1,Y1,X2,Y2:integer; Style:byte);
{}
begin
ListDetails.WX1 := X1;
ListDetails.WY1 := Y1;
ListDetails.WX2 := X2;
ListDetails.WY2 := Y2;
ListDetails.WStyle := Style;
end; { ListSetWin }
procedure ListSetGaps(var ListDetails: ListCfg; LeftGap,RightGap,BotGap,TopGap: byte);
{}
begin
ListDetails.LeftGap := LeftGap;
ListDetails.RightGap := RightGap;
ListDetails.BotGap := BotGap;
ListDetails.TopGap := TopGap;
end; { ListSetGaps }
procedure ListSetColor(var ListDetails: ListCfg; A:TintElement;C:byte);
{}
begin
if A in [FirstListCol..LastListCol] then
ListDetails.Col[A] := C;
end; { ListSetColor }
{**************************}
{** Heading Management **}
{**************************}
procedure ListAssignHeader(var ListDetails: ListCfg; Line:byte; var Heading:string);
{}
begin
if (Line < 1) or (Line > ListMaxHeaders) then
ListSetError(1003)
else
Listdetails.Headers[Line] := @Heading;
end; {ListAssignHeader}
procedure ListAssignFooter(var ListDetails: ListCfg; Line:byte; var Footnote:string);
{}
begin
if (Line < 1) or (Line > ListMaxFooters) then
ListSetError(1003)
else
Listdetails.Footers[Line] := @Footnote;
end; {ListAssignFooter}
procedure ListRemoveHeader(var ListDetails: ListCfg; Line:byte);
{}
begin
if (Line < 1) or (Line > ListMaxHeaders) then
ListSetError(1003)
else
Listdetails.Headers[Line] := nil;
end; {ListRemoveHeader}
procedure ListRemoveFooter(var ListDetails: ListCfg; Line:byte);
{}
begin
if (Line < 1) or (Line > ListMaxFooters) then
ListSetError(1003)
else
Listdetails.Footers[Line] := nil;
end; {ListRemoveFooter}
procedure ListScrollHeader(var ListDetails: ListCfg; On:boolean);
{}
begin
ListDetails.ScrollHeader := On;
end; {ListScrollHeader}
procedure ListScrollFooter(var ListDetails: ListCfg; On:boolean);
{}
begin
ListDetails.ScrollFooter := On;
end; {ListScrollFooter}
procedure GListWriteScrollBar(var ListDetails: ListCfg; Status:gStatus);
{}
var A:byte;
begin
with ListDetails do
begin
if TotalNodes > succ(Y2-Y1) then {need a scroll bar}
begin
if Status in [Activate,HiStatus] then
A := Col[ListScrollbarHi]
else
A := Col[ListScrollbarNorm];
WriteVScrollBar(X2,Y1,Y2,A,ActiveNode,TotalNodes);
end
end;
end; { GListWriteScrollBar }
procedure GListWriteItem(var ListDetails: ListCfg; ItemNum:longint; Status:gStatus);
{}
var
A:byte;
Str:StrScreen;
begin
with ListDetails do
begin
Str := GetStr(DataSource,ItemNum,1,X2-X1-2);
case Status of
Activate, HiStatus, NormStatus: begin
if (AllowTwoColors or ChangeColorsWithTags) and GetBit(DataSource,ItemNum,ColBit) then
A := Col[ListNorm2]
else
A := Col[ListNorm1];
end;
OffStatus: A := Col[ListOff]
end; {case}
if ItemNum = ActiveNode then
begin
Str := ListVars.ListLeft + Str + ListVars.ListRight;
(*
if (Status in [HiStatus,Activate,NormStatus]) then
*)
if (Status in [HiStatus,Activate,NormStatus]) then
begin
if (AllowTwoColors or ChangeColorsWithTags)
and (Status in [HiStatus,Activate])
and GetBit(DataSource,ItemNum,ColBit) then
A := Col[ListHi2]
else if Status = NormStatus then
A := Col[ListHiInActive]
else
A := Col[ListHi1];
end;
end
else
Str := replicate(length(ListVars.ListLeft),' ')+Str+replicate(length(ListVars.ListRight),' ');
Listdetails.ColorHook(ItemNum,ItemNum = ActiveNode,A);
WriteAT(X1,Y1+ItemNum-TopNode,A,Str);
if (Status in [HiStatus,Activate,NormStatus]) and (ItemNum = ActiveNode) then
begin
GListWriteScrollBar(Listdetails,Status);
if Status in [HiStatus,Activate] then
gotoxy(succ(X1),Y1+ItemNum-TopNode);
end;
end;
end; { GListWriteItem }
procedure GListRefresh(var ListDetails: ListCfg; Status:gStatus);
{Updates the list area}
var I : longint;
begin
with ListDetails do
begin
if (ActiveNode < TopNode)
or (ActiveNode > TopNode + Y2 -Y1) then
begin
If Y2 > Y1 then
TopNode := ActiveNode - (Y2 - Y1) div 2
else
TopNode := ActiveNode;
end;
for I := TopNode to TopNode + Y2 - Y1 do
GListWriteItem(ListDetails,I,Status);
end;
end; { GListRefresh }
{****************************}
{** List Scrolling Logic **}
{****************************}
function ListScrollUp(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
ListScrollUp := false;
with ListDetails do
begin
if ActiveNode > TopNode then
dec(ActiveNode)
else if TopNode > 1 then
begin
dec(TopNode);
ActiveNode := TopNode;
ListScrollUp := true;
end;
end;
end; {ListScrollUp}
function ListScrollDown(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
ListScrollDown := false;
with ListDetails do
begin
if ActiveNode < TotalNodes then
begin
if ActiveNode < TopNode + Y2 - Y1 then
inc(ActiveNode)
else
begin
inc(TopNode);
inc(ActiveNode);
ListScrollDown := true;
end;
end;
end;
end; {ListScrollDown}
function ListScrollPgDn(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
with ListDetails do
begin
if ActiveNode < TotalNodes then
begin
ListScrollPgDn := true;
if ActiveNode + succ(Y2-Y1) > TotalNodes then
ActiveNode := TotalNodes
else
begin
inc(TopNode,succ(Y2-Y1));
inc(ActiveNode,succ(Y2-Y1));
end;
end
else
ListScrollPgDn := false;
end;
end; {ListScrollPgDn}
function ListScrollPgUp(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
ListScrollPgUp := false;
with ListDetails do
begin
if ActiveNode > 1 then
begin
if TopNode > 1 then
ListScrollPgUp := true;
if TopNode - succ(Y2-Y1) < 1 then
TopNode := 1
else
dec(TopNode,succ(Y2-Y1));
if ActiveNode - succ(Y2-Y1) < 1 then
ActiveNode := 1
else
dec(ActiveNode,succ(Y2-Y1));
end;
end;
end; {ListScrollPgUp}
function ListScrollHome(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
with ListDetails do
begin
ListScrollHome := (TopNode > 1);
TopNode := 1;
ActiveNode := 1;
end;
end; {ListScrollHome}
function ListScrollEnd(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
with ListDetails do
begin
if TopNode + Y2 - Y1 < TotalNodes then
begin
ListScrollEnd := true;
TopNode := TotalNodes - (Y2 - Y1) ;
end
else
ListScrollEnd := false;
ActiveNode := TotalNodes;
end;
end; {ListScrollEnd}
procedure ListMoveIt(var ListDetails: ListCfg; Direction: byte);
{}
var
Repaint: boolean;
OldAct: integer;
begin
with ListDetails do
begin
OldAct := ActiveNode;
if ((Direction in [1,3,5]) and (ActiveNode = 1))
or ((Direction in [2,4,6]) and (ActiveNode = TotalNodes)) then
exit;
case Direction of
1: Repaint := ListScrollUp(ListDetails);
2: Repaint := ListScrollDown(ListDetails);
3: Repaint := ListScrollPgUp(ListDetails);
4: Repaint := ListScrollPgDn(ListDetails);
5: Repaint := ListScrollHome(ListDetails);
6: Repaint := ListScrollEnd(ListDetails);
end;
if Repaint then
GListRefresh(ListDetails,HiStatus)
else if OldAct <> ActiveNode then
begin
GListWriteItem(ListDetails,OldAct,HiStatus);
GListWriteItem(ListDetails,ActiveNode,HiStatus);
end;
end;
end; { ListMoveIt }
{***************************}
{** List Mouse Handling **}
{***************************}
procedure ListMouseVScroll(var ListDetails: ListCfg);
{}
var
L,M,R: boolean;
X,Y,ElevatorY:byte;
WaitTime: integer;
procedure ScrollUpOne;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2) and (Y = Y1) and L then
ListMoveIt(Listdetails,1);
DelayIt(L,InWindow,WaitTime);
until not L;
end; { ScrollUpOne }
procedure ScrollDownOne;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2) and (Y = Y2) and L then
ListMoveIt(ListDetails,2);
DelayIt(L,InWindow,WaitTime);
until not L;
end; { ScrollDownOne }
procedure ScrollUpward;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if ActiveNode <> 1 then
begin
if (X = X2) and (Y >= Y1) and (Y <= ElevatorY) and L then
ListMoveIt(ListDetails,3); {PgUp effect}
DelayIt(L,InWindow,WaitTime);
end;
until not L;
end; { ScrollUpward }
procedure ScrollDownward;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if ActiveNode <> TotalNodes then
begin
if (X = X2) and (Y <= Y2) and (Y >= ElevatorY) and L then
ListMoveIt(ListDetails,4); {PgDn effect}
DelayIt(L,InWindow,WaitTime);
end;
until not L;
end; { ScrollDownward }
procedure ScrollDragElevator;
{}
var
OldY:byte;
NewActive:longint;
begin
OldY := Y;
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2) and (Y < Y2) and (Y > Y1) and (Y <> OldY) and L then
begin
OldY := Y;
if Y = succ(Y1) then
NewActive := 1
else if Y = pred(Y2) then
NewActive := TotalNodes
else
NewActive := TotalNodes * (Y - Y1) div (Y2-Y1);
if NewActive <> ActiveNode then
begin
ActiveNode := NewActive;
TopNode := NewActive;
GListRefresh(ListDetails,HiStatus);
end;
if WindowHasFocus then
WinDrawTop;
end;
until not L;
end; { ScrollElevator }
begin
with ListDetails do
begin
WaitTime := KeyVars.InitScrollDelay;
InWindow := WindowHasFocus;
repeat
MouseStatusWin(L,M,R,X,Y);
if L and (X = X2) then
begin
if Y = Y1 then
ScrollUpOne
else if Y = Y2 then
ScrollDownOne
else {mouse pressed along scroll bar body}
begin
ElevatorY := GetVScrollBarElevator(Y1,Y2,ActiveNode,TotalNodes);
if ((Y = succ(Y1)) and (Y=ElevatorY) and (ActiveNode > 1))
or (Y > Y1) and (Y < ElevatorY) then
ScrollUpward
else if ((Y = pred(Y2)) and (Y=ElevatorY)
and
(ActiveNode < TotalNodes)
)
or ((Y < Y2) and (Y > ElevatorY)) then
ScrollDownward
else {user is dragging elevator}
ScrollDragElevator;
end;
end;
until not L;
MouseRelease;
end;
end; { ListMouseVScroll }
function ListOnTarget(var ListDetails: ListCfg;X,Y:byte): byte;
{}
begin
with ListDetails do
begin
if (X >= X1) and (X <= X2)
and (Y >= Y1) and (Y <= Y2)
and (Y <= Y1 + TotalNodes - pred(TopNode)) then
begin
ListOnTarget := Y - Y1 + TopNode
end
else
ListOnTarget := 0;
end;
end; { OnTarget }
procedure ListMouseSelect(var ListDetails: ListCfg);
{Called when mouse pressed on field and held down}
var
L,M,R: boolean;
X,Y:byte;
OldAct,
NewAct: integer;
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if L then
begin
OldAct := ActiveNode;
NewAct := ListOnTarget(Listdetails,X,Y);
if (NewAct <> 0) and (NewAct <> OldAct) then
begin
ActiveNode := NewAct;
GListWriteItem(ListDetails,OldAct,HiStatus);
GListWriteItem(ListDetails,ActiveNode,HiStatus);
if WindowHasFocus then
WinDrawTop;
end;
(*
if NewAct = 0 then
CursorOff
else
CursorOn;
*)
end;
until not L;
MouseRelease;
end; {ListMouseSelect}
{********************}
{** Key Handling **}
{********************}
procedure GListProcessKey(var ListDetails: ListCfg;var K:word;X,Y:byte;MakeLocal:boolean);
{}
begin
with ListDetails do
begin
CharHook(K,X,Y); {call user hook}
if MakeLocal then
if IsWinKey(K,X,Y) then
WinProcessKey(K,X,Y);
if (K = 500) or (K = 540) then
begin
if MakeLocal then {convert to local coords}
begin
X := WinLocalX(0,X);
Y := WinLocalY(0,Y);
end;
if K = 500 then
begin
if (X = X2) and (TotalNodes > succ(Y2-Y1)) then
ListMouseVScroll(Listdetails)
else
ListMouseSelect(Listdetails);
end
else if ListOnTarget(Listdetails,X,Y) <> 0 then
K := 540; {double click}
end
else
case K of
331,328: ListMoveIt(ListDetails,1);
333,336: ListMoveIt(ListDetails,2);
329: ListMoveIt(ListDetails,3);
337: ListMoveIt(ListDetails,4);
327: ListMoveIt(ListDetails,5);
335: ListMoveIt(ListDetails,6);
end; {case}
LastKey := K;
HindHook(@ListDetails);
end;
end; { GListProcessKey }
{***************}
{** ListWin **}
{***************}
function RunListStrLL(ListSource:StringLL;Tit:StrScreen):longint;
{}
var
Settings: ListCfg;
Handle: integer;
procedure SetWindow;
{}
begin
with ListVars do
begin
Handle := WinCreate(WX1,WY1,WX2,WY2,WinStyle);
WinSetType(Handle,WMove); {don't allow strectch -- since its used in forms}
WinSetTitle(Handle,Tit);
WinSetShowNum(Handle,false);
WinSetColor(Handle,WinBorder,Tint[ListBorder1]);
WinSetColor(Handle,WinBorder3DOut,Tint[ListBorder1]);
WinSetColor(Handle,WinBorder3DIn,Tint[ListBorder2]);
WinSetColor(Handle,WinBorderOff,Tint[ListBorderOff]);
WinSetColor(Handle,WinIcons,Tint[ListIcons]);
WinSetColor(Handle,WinBody,Tint[ListNorm1]);
WinSetColor(Handle,WinTitle,Tint[ListTitle]);
WinPaint(Handle);
end;
end; {SetWindow}
begin
InitListCFG(Settings);
with Settings do
begin
TotalNodes := ListSource.TotalNodes;
ActiveNode := ListSource.ActiveNode;
TopNode := ListSource.TopNode;
DataSource := @ListSource;
DataType := SourceStrLL;
GetStr := SLGetStr;
X2 := ListVars.WX2-ListVars.WX1-1-2*ord(WStyle in [7,8]);
Y2 := ListVars.WY2-ListVars.WY1-1;
InWindow := true;
end;
CalcColRow(Settings);
SetWindow;
WinDisplay(Handle);
GListRefresh(Settings,HiStatus);
WinDrawAll;
with Settings do
with KeyVars do
repeat
GetInput;
GListProcessKey(Settings,LastKey,LastX,LastY,true);
if (LastKey = 600)
or (LastKey = 27)
or ((LastKey = 540) and (LastX <> 0))
or (LastKey = 13) then
begin
LastAction := SelectHook(@Settings);
if LastAction = Refresh then
begin
TotalNodes := StringLL(dataSource^).TotalNodes;
if (ActiveNode > TotalNodes) or (TopNode > TotalNodes) then
begin
ActiveNode := 1;
TopNode := 1;
end;
GListRefresh(Settings,HiStatus);
end;
end
else
LastAction := none;
WinDrawAll;
until LastAction in [Stop1..Escaped];
WinDispose(Handle);
MouseRelease;
ListVars.LastActiveItem := Settings.ActiveNode;
if KeyVars.LastKey = 27 then
RunListStrLL := 0
else
RunListStrLL := Settings.ActiveNode;
end; { RunListStrLL }
{********************************************}
{** B R O W S I N G L I S T S **}
{********************************************}
procedure SetInnerDimensions(var ListDetails: ListCfg);
{Asseses the window dimensions and sets the list coordinates
X1..Y2 based on the window style and the gapxxx settings}
var
Counter,
I: integer;
begin
with ListDetails do
begin
X1 := 1 + LeftGap;
Y1 := 1 + TopGap;
X2 := WX2-succ(WX1)-2*ord(WStyle in [7,8]) - RightGap;
Y2 := WY2-succ(WY1) - BotGap;
{now adjust for the headers and footers}
Counter := 0;
for I := 1 to ListMaxHeaders do
inc(Counter,ord(Listdetails.Headers[I] <> nil));
inc(Y1,Counter);
Counter := 0;
for I := 1 to ListMaxFooters do
inc(Counter,ord(Listdetails.Footers[I] <> nil));
dec(Y2,Counter);
if Y2 <= Y1 then
Y2 := Y1;
end;
end; { SetInnerDimensions }
procedure RefreshHeadFoot(var ListDetails: ListCfg);
{}
var
Counter,
I: integer;
TempStr: string;
W,X: byte;
begin
with Listdetails do
begin
Counter := 0;
if Scrollheader then
X := StartingCol
else
X := 1;
W := (X2-X1)-ord(TotalNodes > succ(Y2-Y1));
for I := 1 to ListMaxHeaders do
begin
if Listdetails.Headers[I] <> nil then
begin
inc(Counter);
TempStr := copy(Listdetails.Headers[I]^,X,W);
if (TempStr <> '') and (TempStr[1] = '^') then
begin
delete(TempStr,1,1);
WriteBetween(succ(leftGap),X2-X1-RightGap,TopGap+Counter,Tint[ListHeaders],TempStr);
end
else
WriteAT(succ(leftGap),TopGap+Counter,Tint[ListHeaders],padleft(TempStr,W,' '));
end;
end;
Counter := 0;
if ScrollFooter then
X := StartingCol
else
X := 1;
for I := 1 to ListMaxFooters do
begin
if Listdetails.Footers[I] <> nil then
begin
inc(Counter);
TempStr := copy(Listdetails.Footers[I]^,X,W);
if (TempStr <> '') and (TempStr[1] = '^') then
begin
delete(TempStr,1,1);
WriteBetween(succ(leftGap),X2-X1-RightGap,Y2+Counter,Tint[ListHeaders],TempStr);
end
else
WriteAT(succ(leftGap),Y2+Counter,Tint[ListHeaders],padleft(TempStr,W,' '));
end;
end;
end;
end; {RefreshHeadFoot}
procedure BrowseRefresh(var ListDetails: ListCfg);
{Updates the list area}
var
I : longint;
A:byte;
Str:StrScreen;
HScrollBarVisible,
VScrollBarVisible: boolean;
begin
with ListDetails do
begin
VScrollbarVisible := TotalNodes > succ(Y2-Y1);
HScrollbarVisible := LastCol > succ(X2-X1);
for I := TopNode to TopNode + Y2 - Y1 - ord(HScrollbarVisible) do
begin
Str := GetStr(DataSource,I,StartingCol,StartingCol + (X2-X1)-ord(VScrollbarVisible));
if (AllowTwoColors or ChangeColorsWithTags) and GetBit(DataSource,I,ColBit) then
A := Col[ListNorm2]
else
A := Col[ListNorm1];
ColorHook(I,false,A);
WriteAT(X1,Y1+I-TopNode,A,Str);
end;
if VScrollBarVisible then
begin
if (TopNode = TotalNodes) or (TopNode = 1) then
WriteVScrollBar(X2,Y1,Y2-ord(HScrollbarVisible),A,TopNode,TotalNodes)
else
WriteVScrollBar(X2,Y1,Y2-ord(HScrollbarVisible),A,TopNode + (Y2-Y1) ,TotalNodes);
end;
if HScrollBarVisible then
begin
if (StartingCol = LastCol) or (StartingCol = 1) then
WriteHScrollBar(X1,X2-ord(VScrollbarVisible),Y2,Col[ListNorm1],StartingCol,LastCol)
else
WriteHScrollBar(X1,X2-ord(VScrollbarVisible),Y2,Col[ListNorm1],StartingCol + (X2-X1) ,LastCol);
end;
end;
end; { BrowseRefresh }
procedure BrowseWindowStretch(var Listdetails: ListCfg);
{Called when user stretches the window}
var
WP: WStructurePtr;
begin
{First set the listdetails to reflect the revised window dimensions}
WP := WinPtr(0); {top window}
with Listdetails do
begin
WX1 := WP^.X;
WY1 := WP^.Y;
WX2 := WX1 + pred(WP^.Width);
WY2 := WY1 + pred(WP^.Depth);
end;
SetInnerDimensions(Listdetails);
RefreshHeadFoot(Listdetails);
BrowseRefresh(ListDetails);
end; {BrowseWindowStretch}
procedure BrowseMoveIt(var ListDetails: ListCfg; Direction: byte);
{Moves in a specified direction and repaints the list}
begin
with ListDetails do
begin
if ((Direction in [1,3,5]) and (TopNode = 1))
or ((Direction in [7,9]) and (StartingCol = LastCol))
or ((Direction in [8,10]) and (StartingCol = 1))
or ((Direction in [2,4,6]) and (TopNode = TotalNodes)) then
exit;
case Direction of
1: begin
dec(TopNode);
BrowseRefresh(ListDetails);
end;
2: if TopNode < TotalNodes then {down one}
begin
inc(TopNode);
BrowseRefresh(ListDetails);
end;
3: begin {PgUp}
if TopNode - (Y2 - Y1) - ord(LastCol > succ(X2-X1)) < 1 then
TopNode := 1
else
dec(TopNode,Y2 - Y1 - ord(LastCol > succ(X2-X1)));
BrowseRefresh(ListDetails);
end;
4: begin {PgDn}
if TopNode + (Y2 - Y1) - ord(LastCol > succ(X2-X1)) > TotalNodes then
TopNode := TotalNodes
else
inc(TopNode,Y2 - Y1 - ord(LastCol > succ(X2-X1)));
BrowseRefresh(ListDetails);
end;
5: begin {Ctrl-PgUp}
TopNode := 1;
BrowseRefresh(ListDetails);
end;
6: begin
TopNode := TotalNodes;
BrowseRefresh(ListDetails);
end;
7: begin
inc(StartingCol);
if Scrollheader or ScrollFooter then
RefreshHeadFoot(Listdetails);
BrowseRefresh(ListDetails);
end;
8: begin
dec(StartingCol);
if Scrollheader or ScrollFooter then
RefreshHeadFoot(Listdetails);
BrowseRefresh(ListDetails);
end;
9: begin
if StartingCol + X2 - X1 - ord(TotalNodes > succ(Y2-Y1)) > LastCol then
StartingCol := LastCol
else
inc(StartingCol,X2 - X1 - ord(TotalNodes > succ(Y2-Y1)));
if Scrollheader or ScrollFooter then
RefreshHeadFoot(Listdetails);
BrowseRefresh(ListDetails);
end;
10: begin
if StartingCol - (X2 - X1) - ord(TotalNodes > succ(Y2-Y1)) < 1 then
StartingCol := 1
else
dec(StartingCol,X2 - X1 - ord(TotalNodes > succ(Y2-Y1)));
if Scrollheader or ScrollFooter then
RefreshHeadFoot(Listdetails);
BrowseRefresh(ListDetails);
end;
end;
end;
end; { BrowseMoveIt }
procedure BrowseMouseVScroll(var ListDetails: ListCfg);
{}
var
L,M,R: boolean;
X,Y,ElevatorY:byte;
WaitTime: integer;
procedure ScrollUpOne;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2) and (Y = Y1) and L then
BrowseMoveIt(Listdetails,1);
DelayIt(L,InWindow,WaitTime);
until not L;
end; { ScrollUpOne }
procedure ScrollDownOne;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2) and (Y = Y2 - ord(LastCol > succ(X2-X1))) and L then
BrowseMoveIt(ListDetails,2);
DelayIt(L,InWindow,WaitTime);
until not L;
end; { ScrollDownOne }
procedure ScrollUpward;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if TopNode <> 1 then
begin
if (X = X2) and (Y >= Y1) and (Y <= ElevatorY) and L then
BrowseMoveIt(ListDetails,3); {PgUp effect}
DelayIt(L,InWindow,WaitTime);
end;
until not L;
end; { ScrollUpward }
procedure ScrollDownward;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if TopNode <> TotalNodes then
begin
if (X = X2) and (Y <= Y2) and (Y >= ElevatorY) and L then
BrowseMoveIt(ListDetails,4); {PgDn effect}
DelayIt(L,InWindow,WaitTime);
end;
until not L;
end; { ScrollDownward }
procedure ScrollDragElevator;
{}
var
OldY:byte;
NewActive:longint;
begin
OldY := Y;
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2) and (Y < Y2 - ord(LastCol > succ(X2-X1))) and (Y > Y1) and (Y <> OldY) and L then
begin
OldY := Y;
if Y = succ(Y1) then
NewActive := 1
else if Y = pred(Y2) - ord(LastCol > succ(X2-X1)) then
NewActive := TotalNodes
else
NewActive := (TotalNodes * (Y - Y1) div (Y2-Y1)) - (Y2-Y1);
if NewActive <> TopNode then
begin
TopNode := NewActive;
BrowseRefresh(ListDetails);
end;
if WindowHasFocus then
WinDrawTop;
end;
until not L;
end; { ScrollElevator }
begin
with ListDetails do
begin
WaitTime := KeyVars.InitScrollDelay;
InWindow := WindowHasFocus;
repeat
MouseStatusWin(L,M,R,X,Y);
if L and (X = X2) then
begin
if Y = Y1 then
ScrollUpOne
else if Y = Y2 - ord(LastCol > succ(X2-X1)) then
ScrollDownOne
else {mouse pressed along scroll bar body}
begin
ElevatorY := GetVScrollBarElevator(Y1,Y2,TopNode,TotalNodes);
if ((Y = succ(Y1)) and (Y=ElevatorY) and (TopNode > 1))
or (Y > Y1) and (Y < ElevatorY) then
ScrollUpward
else if ((Y = pred(Y2) - ord(LastCol > succ(X2-X1))) and (Y=ElevatorY)
and
(TopNode < TotalNodes)
)
or ((Y < Y2 - ord(LastCol > succ(X2-X1))) and (Y > ElevatorY)) then
ScrollDownward
else {user is dragging elevator}
ScrollDragElevator;
end;
end
else
MouseRelease;
until not L;
MouseRelease;
end;
end; { BrowseMouseVScroll }
procedure BrowseMouseHScroll(var ListDetails: ListCfg);
{}
var
L,M,R: boolean;
X,Y,ElevatorX:byte;
WaitTime: integer;
procedure ScrollLeftOne;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X1) and (Y = Y2) and L then
BrowseMoveIt(Listdetails,8);
DelayIt(L,InWindow,WaitTime);
until not L;
end; { ScrollLeftOne }
procedure ScrollRightOne;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2 - ord(TotalNodes > succ(Y2-Y1))) and (Y = Y2) and L then
BrowseMoveIt(ListDetails,7);
DelayIt(L,InWindow,WaitTime);
until not L;
end; { ScrollRightOne }
procedure ScrollLeftward;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if StartingCol <> 1 then
begin
if (X >= X1) and (X <= ElevatorX) and (Y = Y2) and L then
BrowseMoveIt(ListDetails,10);
DelayIt(L,InWindow,WaitTime);
end;
until not L;
end; { ScrollLeftward }
procedure ScrollRightward;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if TopNode <> TotalNodes then
begin
if (X <= X2) and (X >= ElevatorX) and (Y = Y2) and L then
BrowseMoveIt(ListDetails,9);
DelayIt(L,InWindow,WaitTime);
end;
until not L;
end; { ScrollRightward }
procedure ScrollDragElevator;
{}
var
OldX:byte;
NewActive:longint;
begin
OldX := X;
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (Y = Y2) and (X < X2 - ord(TotalNodes > succ(Y2-Y1))) and (X > X1) and (X <> OldX) and L then
begin
OldX := X;
if X = succ(X1) then
NewActive := 1
else if X = pred(X2) - ord(TotalNodes > succ(Y2-Y1)) then
NewActive := LastCol
else
NewActive := (lastCol * (X - X1) div (X2-X1)) - (X2-X1);
if NewActive <> StartingCol then
begin
StartingCol := NewActive;
if Scrollheader or ScrollFooter then
RefreshHeadFoot(Listdetails);
BrowseRefresh(ListDetails);
end;
if WindowHasFocus then
WinDrawTop;
end;
until not L;
end; { ScrollElevator }
begin
with ListDetails do
begin
WaitTime := KeyVars.InitScrollDelay;
InWindow := WindowHasFocus;
repeat
MouseStatusWin(L,M,R,X,Y);
if L and (Y = Y2) then
begin
if X = X1 then
ScrollLeftOne
else if X = X2 - ord(TotalNodes > succ(Y2-Y1)) then
ScrollRightOne
else {mouse pressed along scroll bar body}
begin
ElevatorX := GetHScrollBarElevator(X1,X2- ord(TotalNodes > succ(Y2-Y1)),StartingCol,LastCol);
if ((X = succ(X1)) and (X=ElevatorX) and (StartingCol > 1))
or (X > X1) and (X < ElevatorX) then
ScrollLeftward
else if ((X = pred(X2) - ord(TotalNodes > succ(Y2-Y1))) and (X=ElevatorX)
and
(StartingCol < LastCol)
)
or ((X < X2 - ord(TotalNodes > succ(Y2-Y1))) and (X > ElevatorX)) then
ScrollRightward
else {user is dragging elevator}
ScrollDragElevator;
end;
end
else
MouseRelease;
until not L;
MouseRelease;
end;
end; { BrowseMouseHScroll }
procedure BrowseProcessKey(var ListDetails: ListCfg;var K:word;X,Y:byte; MakeLocal: boolean);
{}
begin
with ListDetails do
begin
CharHook(K,X,Y); {call user hook}
if MakeLocal then
if IsWinKey(K,X,Y) then
WinProcessKey(K,X,Y);
K := CapitalWord(K);
if (K = 500) then
begin
if MakeLocal then {convert to local coords}
begin
X := WinLocalX(0,X);
Y := WinLocalY(0,Y);
end;
if (X = X2) and (TotalNodes > succ(Y2-Y1)) then
BrowseMouseVScroll(Listdetails)
else if (Y = Y2) and (LastCol > succ(X2-X1)) then
BrowseMouseHScroll(Listdetails)
else
MouseRelease;
end
else
case K of
328: BrowseMoveIt(Listdetails,1);
336: BrowseMoveIt(Listdetails,2);
329: BrowseMoveIt(Listdetails,3);
337: BrowseMoveIt(Listdetails,4);
327: if StartingCol > 1 then
begin
StartingCol := 1;
if Scrollheader or ScrollFooter then
RefreshHeadFoot(Listdetails);
BrowseRefresh(ListDetails);
end;
335: if StartingCol < LastCol then
begin
StartingCol := LastCol;
if Scrollheader or ScrollFooter then
RefreshHeadFoot(Listdetails);
BrowseRefresh(ListDetails);
end;
388: BrowseMoveIt(Listdetails,5);
374: BrowseMoveIt(Listdetails,6);
331: BrowseMoveIt(Listdetails,8);
333: BrowseMoveIt(Listdetails,7);
9: BrowseMoveIt(Listdetails,9);
271: BrowseMoveIt(Listdetails,10);
27,600: LastAction := Escaped;
602: if WindowHasFocus then
BrowseWindowStretch(Listdetails);
end; {case}
LastKey := K;
HindHook(@ListDetails);
end;
end; { BrowseProcessKey }
function BrowseCreateWin(WX1,WY1,WX2,WY2,WStyle:byte):byte;
{}
begin
BrowseCreateWin := WinCreate(WX1,WY1,WX2,WY2,WStyle);
end; { BrowseCreateWin }
procedure DisplayBrowseEngine(Handle:integer; var ListDetails: ListCfg;Tit:StrScreen);
{}
procedure SetWindow;
{}
begin
with ListDetails do
with ListVars do
begin
WinSetType(Handle,WrapWinType);
WinSetTitle(Handle,Tit);
WinSetShowNum(Handle,false);
WinSetColor(Handle,WinBorder,Listdetails.Col[ListBorder1]);
WinSetColor(Handle,WinBorder3DOut,Listdetails.Col[ListBorder1]);
WinSetColor(Handle,WinBorder3dIn,Listdetails.Col[ListBorder2]);
WinSetColor(Handle,WinBorderOff,Listdetails.Col[ListBorderOff]);
WinSetColor(Handle,WinIcons,Listdetails.Col[ListIcons]);
WinSetColor(Handle,WinBody,Listdetails.Col[ListNorm1]);
WinSetColor(Handle,WinTitle,Listdetails.Col[ListTitle]);
if ListDetails.ColWidth <> 0 then
WinSetMinSize(Handle,ListDetails.ColWidth+2+2*ord(WinStyle in [7,8]),WinVars.MinDepth);
WinPaint(Handle);
end;
end; {SetWindow}
begin
SetWindow;
WinDisplay(Handle);
RefreshHeadFoot(Listdetails);
BrowseRefresh(ListDetails);
ListDetails.HindHook(@ListDetails); {call it once after window is created}
end; { DisplayBrowseEngine }
procedure RunBrowse(var ListDetails: ListCfg;Tit:StrScreen);
{}
var
Handle: integer;
begin
with ListDetails do
begin
if WX1 = 0 then {user hasn't set the window}
begin
WX1 := ListVars.WX1;
WY1 := ListVars.WY1;
WX2 := ListVars.WX2;
WY2 := ListVars.WY2;
end;
Handle := BrowseCreateWin(WX1,WY1,WX2,WY2,WStyle);
if Handle = 0 then
ListSetError(1004);
end;
SetInnerDimensions(Listdetails);
ListDetails.InWindow := true;
DisplayBrowseEngine(Handle,Listdetails,Tit);
WinDrawAll;
with Listdetails do
with KeyVars do
repeat
GetInput;
BrowseProcessKey(ListDetails,LastKey,LastX,LastY,true);
WinDrawAll;
until LastAction in [Stop1..Escaped];
WinDispose(Handle);
MouseRelease;
end; {RunBrowse}
procedure RunBrowseFile(Fname:PathStr;Tit:StrScreen);
{}
var
DLL: DoubleLL;
Result: integer;
Config: ListCfg;
begin
InitDLLStr(DLL);
DLLSetActiveList(DLL);
Result := DLLLoadFromFile(Fname);
case Result of
1,2: ListSetError(1001);
3: ListSetError(1002);
else
begin
InitListCFG(Config);
ListAssignDLL(Config,DLL);
RunBrowse(Config,Tit);
end;
end;
DLLDestroy;
DLLActivatePrevList;
end; { RunBrowseFile }
{*********************************************}
{** W R A P P I N G L I S T S **}
{*********************************************}
procedure ListSetTagging(var ListDetails: ListCfg;On:boolean);
{}
begin
ListDetails.AllowTagging := On;
end; { ListSetTagging }
procedure ListSetTwoColors(var ListDetails: ListCfg;On:boolean);
{}
begin
ListDetails.AllowTwoColors := On;
end; { ListSetTwoColors }
procedure ListSetTagColor(var ListDetails: ListCfg; On:boolean);
{}
begin
ListDetails.ChangeColorsWithTags := On;
end; { ListSetColorWithTag }
procedure ListSetColWidth(var ListDetails: ListCfg; Width:byte);
{}
begin
ListDetails.ColWidth := Width;
CalcColRow(Listdetails);
end; { ListSetColWidth }
procedure ListAssignHindHook(var ListDetails: ListCfg; Proc:ListHindHook);
{}
begin
ListDetails.HindHook := Proc;
end; { ListAssignHindHook }
procedure ListAssignCharHook(var ListDetails: ListCfg; Proc:KeyPressedHook);
{}
begin
ListDetails.CharHook := Proc;
end; { ListAssignCharHook }
procedure ListAssignSelectHook(var ListDetails: ListCfg; Proc:ListSelectHook);
{}
begin
ListDetails.SelectHook := Proc;
end; { ListAssignSelectHook }
procedure ListAssignColorHook(var ListDetails: ListCfg; Proc:ListColorHook);
{}
begin
ListDetails.ColorHook := Proc;
end; { ListColorSelectHook }
procedure ListRemoveColorHook(var ListDetails: ListCfg);
{}
begin
ListDetails.ColorHook := NoListColorHook;
end; { ListRemoveColorHook }
procedure ListRemoveCharHook(var ListDetails: ListCfg);
{}
begin
ListDetails.CharHook := NoListCharHook;
end; { ListRemoveCharHook }
procedure ListRemoveHindHook(var ListDetails: ListCfg);
{}
begin
ListDetails.HindHook := NoListHindHook;
end; { ListRemoveHindHook }
procedure ListRemoveSelectHook(var ListDetails: ListCfg);
{}
begin
ListDetails.SelectHook := ListDefaultSelectHook;
end; { ListRemoveSelectHook }
procedure ListAssignArray(var ListDetails: ListCfg; var ListSource; StrLen:Byte;ArrayElements:byte);
{}
begin
with ListDetails do
begin
DataSource := @ListSource;
DataType := SourceArray;
TotalNodes := ArrayElements;
ActiveNode := 1;
TopNode := 1;
StrLength := Strlen;
GetStr := ArrayGetStrFunc;
end;
end; {ListAssignArray}
procedure ListAssignSLL(var ListDetails: ListCfg; var TheList:SingleLL);
{}
begin
with ListDetails do
begin
DataSource := @TheList;
DataType := SourceSLL;
TotalNodes := TheList.TotalNodes;
ActiveNode := 1;
TopNode := 1;
GetStr := SLLGetStrFunc;
GetBit := SLLGetBitFunc;
SetBit := SLLSetBitFunc;
end;
end; {ListAssignSLL}
procedure ListAssignDLL(var ListDetails: ListCfg; var TheList:DoubleLL);
{}
begin
with ListDetails do
begin
DataSource := @TheList;
DataType := SourceDLL;
TotalNodes := TheList.TotalNodes;
ActiveNode := 1;
TopNode := 1;
GetStr := DLLGetStrFunc;
GetBit := DLLGetBitFunc;
SetBit := DLLSetBitFunc;
end;
end; {ListAssignDLL}
procedure ListAssignCustom(var ListDetails: ListCfg; Total:longint; Proc:ListGetStrFunc);
{}
begin
with ListDetails do
begin
GetStr := Proc;
DataType := SourceCustom;
TotalNodes := Total;
AllowTagging := false;
ActiveNode := 1;
TopNode := 1;
end;
end; {ListAssignCustom}
procedure RecalcListDimensions(var ListDetails: ListCfg);
{}
var
ListWidth: byte;
begin
with ListDetails do
begin
if ColWidth <> 0 then
RealColWidth := ColWidth;
ListWidth := X2-X1;
if RealColWidth > ListWidth then
RealColWidth := ListWidth;
ColCount := ListWidth div RealColWidth;
LastColWidth := ListWidth - ColCount * RealColWidth;
if LastColWidth = 0 then
LastColWidth := RealColWidth
else
inc(ColCount);
RowCount := succ(Y2-Y1);
end;
end; { RecalcListDimensions }
procedure WrapListWriteItem(var ListDetails: ListCfg; ItemNum:longint; Status:gStatus);
{}
var
X,Y,
A:byte;
Str:StrScreen;
AvailWidth,
TextWidth: shortint;
begin
with ListDetails do
begin
if TotalNodes = 0 then
exit;
if (ColCount > 1)
and (ItemNum - pred(TopNode) > RowCount * pred(ColCount))
and (LastColWidth <> RealColWidth) then
AvailWidth := LastColWidth
else
AvailWidth := RealColWidth;
if ItemNum <= TotalNodes then
begin
with ListVars do
TextWidth := AvailWidth
- length(ListLeft)
- length(ListRight)
- ord(AllowTagging) * length(ListTag);
if TextWidth > 0 then
Str := GetStr(Listdetails.DataSource,ItemNum,1,TextWidth)
else
Str := '';
if AllowTagging then {add the tag character}
begin
if GetBit(DataSource,ItemNum,TagBit) then
Str := ListVars.ListTag + Str
else
Str := replicate(length(ListVars.ListTag),' ')+Str;
end;
if (AllowTwoColors or ChangeColorsWithTags)
and GetBit(DataSource,ItemNum,ColBit) then
A := Col[ListNorm2]
else
A := Col[ListNorm1];
if ItemNum = ActiveNode then
begin
Str := ListVars.ListLeft + Str + ListVars.ListRight;
(*
if (Status in [HiStatus,Activate]) then
begin
*)
if (AllowTwoColors or ChangeColorsWithTags) and GetBit(DataSource,ItemNum,ColBit) then
A := Col[ListHi2]
else
A := Col[ListHi1];
(*
end;
*)
end
else
Str := replicate(length(ListVars.ListLeft),' ')+Str+replicate(length(ListVars.ListRight),' ');
end
else
begin
A := Col[ListNorm1];
Str := replicate(AvailWidth,' ');
end;
{now we've created the item string we have to figure out where
to write it}
if ItemNum - pred(TopNode) <= RowCount then
X := X1
else
X := pred(X1) + succ(RealColWidth*((ItemNum - TopNode) div RowCount));
if (ItemNum - pred(TopNode)) mod RowCount = 0 then
Y := pred(Y1) + RowCount
else
Y := pred(Y1) + (ItemNum - pred(TopNode)) mod RowCount;
if length(Str) > AvailWidth then
Str := copy(Str,1,AvailWidth);
ColorHook(ItemNum,ItemNum = ActiveNode,A);
WriteAT(X,Y,A,Str);
if (Status in [HiStatus,Activate]) and (ItemNum = ActiveNode) then
begin
GListWriteScrollBar(Listdetails,HiStatus);
gotoxy(X,Y);
end;
end;
end; { WrapListWriteItem }
procedure WrapListRefresh(var ListDetails: ListCfg; Status:gStatus);
{Updates the list area}
var I : longint;
begin
with ListDetails do
begin
if (LastColWidth = RealColWidth) or (ColCount = 1) then
I := ColCount*RowCount
else
I := pred(ColCount)*RowCount;
if (ActiveNode < TopNode)
or (ActiveNode > pred(TopNode) + I)
or (ActiveNode > TotalNodes) then
ActiveNode := TopNode;
for I := TopNode to (pred(TopNode) + (RowCount * ColCount)) do
WrapListWriteItem(ListDetails,I,Status);
end;
end; {WrapListRefresh}
function WrapScrollUp(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
WrapScrollUp := false;
with ListDetails do
begin
if ActiveNode > TopNode then
dec(ActiveNode)
else if TopNode > 1 then
begin
dec(TopNode);
ActiveNode := TopNode;
WrapScrollUp := true;
end;
end;
end; {WrapScrollUp}
function WrapScrollDown(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
var LastPick : longint;
begin
WrapScrollDown := false;
with ListDetails do
begin
if ActiveNode < TotalNodes then
begin
if (ColCount = 1) or (LastColWidth = RealColWidth) then
LastPick := ColCount * RowCount
else
LastPick := pred(ColCount) * RowCount;
if ActiveNode < pred(TopNode) + LastPick then
inc(ActiveNode)
else
begin
inc(TopNode);
inc(ActiveNode);
WrapScrollDown := true;
end;
end;
end;
end; {WrapScrollDown}
function WrapScrollLeft(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
with ListDetails do
begin
if (ColCount = 1) or ((ColCount = 2) and (LastColWidth <> RealColWidth)) then
WrapScrollLeft := WrapScrollUp(ListDetails)
else
begin
if ActiveNode > pred(TopNode) + RowCount then {not in first Col}
begin
WrapScrollLeft := false;
dec(ActiveNode,RowCount);
end
else if TopNode > RowCount then
begin
WrapScrollLeft := true;
dec(ActiveNode,RowCount);
dec(TopNode,RowCount);
end
else
begin
WrapScrollLeft := true;
ActiveNode := 1;
TopNode := 1;
end;
end;
end;
end; {WrapScrollLeft}
function WrapScrollRight(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
with ListDetails do
begin
if (ColCount = 1) or ((ColCount = 2) and (LastColWidth <> RealColWidth)) then
WrapScrollRight := WrapScrollDown(ListDetails)
else
begin
inc(ActiveNode,RowCount);
if ActiveNode > TotalNodes then
ActiveNode := TotalNodes;
if ActiveNode <= pred(TopNode) + ( (ColCount-ord(LastColWidth <> RealColWidth)) * RowCount) then
WrapScrollRight := false
else
begin
WrapScrollRight := true;
inc(TopNode,RowCount);
if TopNode > TotalNodes then
TopNode := TotalNodes;
end;
end;
end;
end; {WrapScrollRight}
function WrapScrollPgDn(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
with ListDetails do
begin
if pred(TopNode) + RowCount < TotalNodes then
begin
inc(TopNode,RowCount);
ActiveNode := TopNode;
WrapScrollPgDn := true;
end
else
WrapScrollPgDn := false;
end;
end; {WrapScrollPgDn}
function WrapScrollPgUp(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
with ListDetails do
begin
if ActiveNode > 1 then
begin
if TopNode > 1 then
begin
WrapScrollPgUp := true;
dec(TopNode,RowCount);
dec(ActiveNode,RowCount);
if TopNode < 1 then
TopNode := 1;
if ActiveNode < TopNode then
ActiveNode := TopNode;
end
else
begin
WrapScrollPgUp := false;
ActiveNode := 1;
end;
end;
end;
end; {WrapScrollPgUp}
function WrapScrollHome(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
with ListDetails do
begin
WrapScrollHome := (TopNode > 1);
TopNode := 1;
ActiveNode := 1;
end;
end; {WrapScrollHome}
function WrapScrollEnd(var ListDetails: ListCfg): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
begin
with ListDetails do
begin
if TopNode + pred((ColCount -ord(not (LastColWidth = RealColWidth))) * RowCount)
>= TotalNodes then {last node on display}
WrapScrollEnd := false
else
begin
WrapScrollEnd := true;
TopNode := TotalNodes;
end;
ActiveNode := TotalNodes;
end;
end; {WrapScrollEnd}
function WrapScrollChar(var ListDetails: ListCfg;Ch:char): boolean;
{Updates the ActiveNode and TopNode parameters and returns
true if TopNode is modified, i.e. if the list needs to be
refreshed}
var
LastPick,
L: longint;
Str:string[1];
Found:boolean;
begin
WrapScrollChar := false;
with ListDetails do
begin
{first search from top of list looking for match}
L := 0;
Found := false;
while not found and (L <= TotalNodes) do
begin
inc(L);
Str := GetStr(Listdetails.DataSource,L,1,1);
Found := Str[1] = Ch;
end;
if Found then
begin
ActiveNode := L;
if (ColCount = 1) or (LastColWidth = RealColWidth) then
LastPick := ColCount * RowCount
else
LastPick := pred(ColCount) * RowCount;
if (ActiveNode < TopNode)
or (ActiveNode > pred(TopNode) + LastPick) then
begin
TopNode := ActiveNode;
WrapScrollChar := true;
end;
end;
end;
end; {WrapScrollChar}
{*********************}
{** Tagging Procs **}
{*********************}
procedure ToggleTagState(var ListDetails: ListCfg);
{}
var On: boolean;
begin
with ListDetails do
if AllowTagging then
begin
On := not GetBit(DataSource,ActiveNode,TagBit);
SetBit(DataSource,ActiveNode,TagBit,On);
if ChangeColorsWithTags then
SetBit(DataSource,ActiveNode,ColBit,On);
WrapListWriteItem(Listdetails,ActiveNode,HiStatus);
end;
end; { ToggleTagState }
procedure SetTag(var ListDetails: ListCfg; On: boolean);
{}
var State: boolean;
begin
with ListDetails do
if AllowTagging then
begin
State := GetBit(DataSource,ActiveNode,TagBit);
if State <> On then
begin
SetBit(DataSource,ActiveNode,TagBit,On);
if ChangeColorsWithTags then
SetBit(DataSource,ActiveNode,ColBit,On);
WrapListWriteItem(Listdetails,ActiveNode,HiStatus);
end;
end;
end; { SetTag }
procedure SetTagAll(var ListDetails: ListCfg; On: boolean);
{}
var I : longint;
begin
with ListDetails do
if AllowTagging then
begin
for I := 1 to TotalNodes do
begin
SetBit(DataSource,I,TagBit,On);
if ChangeColorsWithTags then
SetBit(DataSource,I,ColBit,On);
end;
WrapListRefresh(ListDetails,HiStatus)
end;
end; { SetTagAll }
procedure WrapMoveIt(var ListDetails: ListCfg; Direction: byte);
{}
var
Repaint: boolean;
OldAct: longint;
begin
with ListDetails do
begin
OldAct := ActiveNode;
if ((Direction in [1,3,5]) and (ActiveNode = 1))
or ((Direction in [2,4,6]) and (ActiveNode = TotalNodes)) then
exit;
case Direction of
1: Repaint := WrapScrollUp(ListDetails);
2: Repaint := WrapScrollDown(ListDetails);
3: Repaint := WrapScrollPgUp(ListDetails);
4: Repaint := WrapScrollPgDn(ListDetails);
5: Repaint := WrapScrollHome(ListDetails);
6: Repaint := WrapScrollEnd(ListDetails);
7: Repaint := WrapScrollLeft(ListDetails);
8: Repaint := WrapScrollRight(ListDetails);
end;
if Repaint then
WrapListRefresh(ListDetails,HiStatus)
else if OldAct <> ActiveNode then
begin
WrapListWriteItem(ListDetails,OldAct,HiStatus);
WrapListWriteItem(ListDetails,ActiveNode,HiStatus);
end;
end;
end; { WrapMoveIt }
procedure WrapMouseVScroll(var ListDetails: ListCfg);
{}
var
L,M,R: boolean;
X,Y,ElevatorY:byte;
WaitTime: integer;
procedure ScrollUpOne;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2) and (Y = Y1) and L then
WrapMoveIt(Listdetails,1);
DelayIt(L,InWindow,WaitTime);
until not L;
end; { ScrollUpOne }
procedure ScrollDownOne;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2) and (Y = Y2) and L then
WrapMoveIt(ListDetails,2);
DelayIt(L,InWindow,WaitTime);
until not L;
end; { ScrollDownOne }
procedure ScrollUpward;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if ActiveNode <> 1 then
begin
if (X = X2) and (Y >= Y1) and (Y <= ElevatorY) and L then
WrapMoveIt(ListDetails,3); {PgUp effect}
DelayIt(L,InWindow,WaitTime);
end;
until not L;
end; { ScrollUpward }
procedure ScrollDownward;
{}
begin
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if ActiveNode <> TotalNodes then
begin
if (X = X2) and (Y <= Y2) and (Y >= ElevatorY) and L then
WrapMoveIt(ListDetails,4); {PgDn effect}
DelayIt(L,InWindow,WaitTime);
end;
until not L;
end; { ScrollDownward }
procedure ScrollDragElevator;
{}
var
OldY:byte;
NewActive:longint;
begin
OldY := Y;
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if (X = X2) and (Y < Y2) and (Y > Y1) and (Y <> OldY) and L then
begin
OldY := Y;
if Y = succ(Y1) then
NewActive := 1
else if Y = pred(Y2) then
NewActive := TotalNodes
else
NewActive := TotalNodes * (Y - Y1) div (Y2-Y1);
if NewActive <> ActiveNode then
begin
ActiveNode := NewActive;
TopNode := NewActive;
WrapListRefresh(ListDetails,HiStatus);
end;
if WindowHasFocus then
WinDrawTop;
end;
until not L;
end; { ScrollElevator }
begin
with ListDetails do
begin
InWindow := WindowHasFocus;
WaitTime := KeyVars.InitScrollDelay;
repeat
MouseStatusWin(L,M,R,X,Y);
if L and (X = X2) then
begin
if Y = Y1 then
ScrollUpOne
else if Y = Y2 then
ScrollDownOne
else {mouse pressed along scroll bar body}
begin
ElevatorY := GetVScrollBarElevator(Y1,Y2,ActiveNode,TotalNodes);
if ((Y = succ(Y1)) and (Y=ElevatorY) and (ActiveNode > 1))
or (Y > Y1) and (Y < ElevatorY) then
ScrollUpward
else if ((Y = pred(Y2)) and (Y=ElevatorY)
and
(ActiveNode < TotalNodes)
)
or ((Y < Y2) and (Y > ElevatorY)) then
ScrollDownward
else {user is dragging elevator}
ScrollDragElevator;
end;
end;
until not L;
MouseRelease;
end;
end; { WrapMouseVScroll }
function WrapTargetPick(var ListDetails: ListCfg;X,Y:byte): longint;
{return the pick number of the pick pointed to by
the coordinates X,Y. If no pick is at those coordinates, a
0 is returned}
begin
with ListDetails do
begin
if (X >= X1)
and (X < X2) {last column is for scroll bar}
and (Y >= Y1)
and (Y <= Y2)
then
begin
X := succ(X - X1);
Y := succ(Y - Y1);
if X mod RealColWidth = 0 then
X := X div RealColWidth
else
X := succ(X div RealColWidth);
if (X < ColCount)
or ((X = ColCount) and (LastColWidth = RealColWidth)) then
begin
if TopNode + pred(pred(X)*RowCount + Y) <= TotalNodes then
begin
WrapTargetPick := pred(TopNode) + pred(X)*RowCount + Y;
exit;
end;
end;
end;
WrapTargetPick := 0;
end;
end; {WrapTargetPick}
procedure WrapMouseSelect(var ListDetails: ListCfg);
{Called when mouse pressed on field and held down}
var
L,M,R: boolean;
X,Y:byte;
OldAct,
NewAct: longint;
function OnActiveNode: boolean;
{}
begin
MouseStatusWin(L,M,R,X,Y);
with ListDetails do
OnActiveNode := (ActiveNode = WrapTargetPick(Listdetails,X,Y));
end; { OnActiveNode }
function CheckforTagChange:boolean;
{}
begin
CheckForTagChange := false;
with Listdetails do
if AllowTagging then
begin
if OnActiveNode and L then
begin
ToggleTagState(Listdetails);
if WindowHasFocus then
WinDrawTop;
MouseRelease;
if OnActiveNode then
CheckForTagChange := true
else
ToggleTagState(Listdetails);
end;
end;
end; { CheckforTagChange }
begin
if not CheckForTagChange then
with ListDetails do
repeat
MouseStatusWin(L,M,R,X,Y);
if L then
begin
OldAct := ActiveNode;
NewAct := WrapTargetPick(Listdetails,X,Y);
if (NewAct <> 0) then
begin
if (NewAct <> OldAct) then
begin
ActiveNode := NewAct;
WrapListWriteItem(ListDetails,OldAct,HiStatus);
WrapListWriteItem(ListDetails,ActiveNode,HiStatus);
if WindowHasFocus then
WinDrawTop;
end;
(*
CursorOn;
*)
end
else
(*
CursorOff;
*);
end;
until not L;
MouseRelease;
end; {WrapMouseSelect}
procedure WrapWindowStretch(var Listdetails: ListCfg);
{Called when user stretches the window}
var
WP: WStructurePtr;
begin
{First set the listdetails to reflect the revised window dimensions}
WP := WinPtr(0); {top window}
with Listdetails do
begin
WX1 := WP^.X;
WY1 := WP^.Y;
WX2 := WX1 + pred(WP^.Width);
WY2 := WY1 + pred(WP^.Depth);
end;
SetInnerDimensions(Listdetails);
CalcColRow(Listdetails);
ReCalcListDimensions(ListDetails);
RefreshHeadFoot(Listdetails);
WrapListRefresh(ListDetails,HiStatus);
WinDrawAll;
end; {WrapWindowStretch}
procedure WrapListProcessKey(var ListDetails: ListCfg;var K:word;X,Y:byte;MakeLocal:boolean);
{}
var
Ch: char;
OldAct:longint;
begin
with ListDetails do
begin
CharHook(K,X,Y); {call user hook}
if MakeLocal then
if IsWinKey(K,X,Y) then
WinProcessKey(K,X,Y);
K := CapitalWord(K);
if (K = 500) or (K = 540) then
begin
if MakeLocal then {convert to local coords}
begin
X := WinLocalX(0,X);
Y := WinLocalY(0,Y);
end;
if (K = 500) then
begin
if (X = X2) and (TotalNodes > succ(Y2-Y1)) then
WrapMouseVScroll(Listdetails)
else
WrapMouseSelect(Listdetails);
end
else if WrapTargetPick(Listdetails,X,Y) <> 0 then
K := 540; {double click}
end
else if K = ListVars.ToggleKey then
ToggleTagState(Listdetails)
else if K = ListVars.TagKey then
SetTag(Listdetails,true)
else if K = ListVars.UnTagKey then
SetTag(Listdetails,false)
else if K = ListVars.TagAllKey then
SetTagAll(Listdetails,true)
else if K = ListVars.UnTagAllKey then
SetTagAll(Listdetails,false)
else
case K of
328: WrapMoveIt(ListDetails,1);
336: WrapMoveIt(ListDetails,2);
329: WrapMoveIt(ListDetails,3);
337: WrapMoveIt(ListDetails,4);
327: WrapMoveIt(ListDetails,5);
335: WrapMoveIt(ListDetails,6);
331: WrapMoveIt(ListDetails,7);
333: WrapMoveIt(ListDetails,8);
602: if WindowHasFocus then
WrapWindowStretch(Listdetails);
else if (K >= 55) and (K <= 255) then
begin
Ch := chr(CapitalWord(K));
OldAct := ActiveNode;
if WrapScrollChar(Listdetails,Ch) then
WrapListRefresh(ListDetails,HiStatus)
else if OldAct <> ActiveNode then
begin
WrapListWriteItem(ListDetails,OldAct,HiStatus);
WrapListWriteItem(ListDetails,ActiveNode,HiStatus);
end;
end;
end; {case}
LastKey := K;
HindHook(@ListDetails);
end;
end; { WrapListProcessKey }
function DisplayListEngine(var ListDetails: ListCfg;Tit:StrScreen): byte;
{INTERNAL}
var
Handle: integer;
procedure SetWindow;
{}
begin
with ListVars do
begin
with ListDetails do
Handle := WinCreate(WX1,WY1,WX2,WY2,WStyle);
WinSetType(Handle,WrapWinType);
WinSetTitle(Handle,Tit);
WinSetShowNum(Handle,false);
WinSetColor(Handle,WinBorder,Listdetails.Col[ListBorder1]);
WinSetColor(Handle,WinBorder3DOut,Listdetails.Col[ListBorder1]);
WinSetColor(Handle,WinBorder3dIn,Listdetails.Col[ListBorder2]);
WinSetColor(Handle,WinBorderOff,Listdetails.Col[ListBorderOff]);
WinSetColor(Handle,WinIcons,Listdetails.Col[ListIcons]);
WinSetColor(Handle,WinBody,Listdetails.Col[ListNorm1]);
WinSetColor(Handle,WinTitle,Listdetails.Col[ListTitle]);
if ListDetails.ColWidth <> 0 then
WinSetMinSize(Handle,ListDetails.ColWidth+2+2*ord(WinStyle in [7,8]),WinVars.MinDepth);
WinPaint(Handle);
end;
end; {SetWindow}
begin
with ListDetails do
begin
if WX1 = 0 then {user hasn't set the window}
begin
WX1 := ListVars.WX1;
WY1 := ListVars.WY1;
WX2 := ListVars.WX2;
WY2 := ListVars.WY2;
end;
if AllowTagging then {Jubelt}
inc(WX2);
end;
SetInnerDimensions(Listdetails);
ListDetails.InWindow := true;
CalcColRow(Listdetails);
ReCalcListDimensions(ListDetails);
SetWindow;
WinDisplay(Handle);
RefreshHeadFoot(Listdetails);
WrapListRefresh(ListDetails,HiStatus);
ListDetails.HindHook(@ListDetails); {call it once after window is created}
DisplayListEngine := Handle;
end; {DisplayListEngine}
procedure ProcessListInput(var ListDetails: ListCfg;OnDeskTop:boolean);
{}
begin
with Listdetails do
with KeyVars do
begin
WrapListProcessKey(ListDetails,LastKey,LastX,LastY,true);
if not OnDeskTop
and (
(LastKey = 600)
or (LastKey = 27)
or ((LastKey = 540) and (LastX <> 0))
or (LastKey = 13)
) then
begin
LastAction := SelectHook(@ListDetails);
if LastAction = Refresh then
begin
case DataType of
SourceStrLL: TotalNodes := StringLL(dataSource^).TotalNodes;
SourceSLL: TotalNodes := LinkVars.ActiveSLL^.TotalNodes;
SourceDLL: TotalNodes := LinkVars.ActiveDLL^.TotalNodes;
end;
ActiveNode := 1;
TopNode := 1;
WrapListRefresh(ListDetails,HiStatus)
end;
end
else
begin
if LastKey = 600 then
LastAction := Escaped
else
LastAction := none;
end;
end;
end; { ProcessListInput }
procedure RunList(var ListDetails: ListCfg;Tit:StrScreen);
{}
var
Handle: integer;
begin
Handle := DisplayListEngine(Listdetails,Tit);
WinDrawAll;
with Listdetails do
with KeyVars do
repeat
GetInput;
ProcessListInput(Listdetails,false);
WinDrawAll;
until LastAction in [Stop1..Escaped];
ListVars.LastActiveItem := ListDetails.ActiveNode;
WinDispose(Handle);
MouseRelease;
end; {RunList}
{**************************}
{** Desktop Management **}
{**************************}
{$IFOPT F-}
{$DEFINE FOFF}
{$F+}
{$ENDIF}
function ListCloseHandler(Handle: integer):boolean;
{}
var
WinP: WStructurePtr;
begin
WinP := WinPtr(Handle);
if ListCfg(Winp^.UserData^).DeskListCloseCallBack(Winp^.UserData,Handle) then
begin
WinDispose(Handle);
ListCloseHandler := true;
end
else
ListCloseHandler := false;
end; {ListCloseHandler}
function BrowseFileCloseHandler(Handle: integer):boolean;
{}
var
WinP: WStructurePtr;
begin
WinP := WinPtr(Handle);
with ListCfg(Winp^.UserData^) do
DLLSetActiveList(DoubleLL(DataSource^));
DLLDestroy;
DLLActivatePrevList;
freemem(WinP^.UserData,sizeof(DeskBrowseFileInfo));
WinDispose(Handle);
BrowseFileCloseHandler := true;
end; {BrowseFileCloseHandler}
procedure ListProcessKeyOnDesktop;
{}
var
Handle: integer;
WinP: WStructurePtr;
LDP : ^ListCfg;
begin
Handle := WinWithFocus;
WinP := WinPtr(Handle);
LDP := Winp^.UserData;
ProcessListInput(LDP^,true);
if LDP^.LastAction in [Stop1..Escaped] then
if ListCloseHandler(Handle) then
{Close aborted};
end; { ListProcessKeyOnDesktop }
procedure BrowseProcessKeyOnDesktop;
{}
var
Handle: integer;
WinP: WStructurePtr;
LDP : ^ListCfg;
K: word;
X,Y: byte;
begin
Handle := WinWithFocus;
WinP := WinPtr(Handle);
LDP := Winp^.UserData;
with KeyVars do
begin
K := LastKey;
X := lastX;
Y := LastY;
end;
BrowseProcessKey(LDP^,K,X,Y,true);
(*
if LDP^.LastAction in [Stop1..Escaped] then
ListCloseHandler(Handle);
*)
end; { BrowseProcessKeyOnDesktop }
procedure BrowseFileProcessKeyOnDesktop;
{}
var
Handle: integer;
WinP: WStructurePtr;
LDP : ^ListCfg;
K: word;
X,Y: byte;
begin
Handle := WinWithFocus;
WinP := WinPtr(Handle);
LDP := @DeskBrowseFileInfo(Winp^.UserData^).Cfg;
with KeyVars do
begin
K := LastKey;
X := lastX;
Y := LastY;
end;
BrowseProcessKey(LDP^,K,X,Y,true);
if LDP^.LastAction in [Stop1..Escaped] then
if BrowseFileCloseHandler(Handle) then
{close aborted};
end; { BrowseFileProcessKeyOnDesktop }
procedure ListFocusHandler(Handle: integer);
{}
var
WinP: WStructurePtr;
begin
WinP := WinPtr(Handle);
with ListCfg(WinP^.UserData^) do
begin
case DataType of
SourceSLL: SLLSetActiveList(SingleLL(DataSource^));
SourceDLL: DLLSetActiveList(DoubleLL(DataSource^));
end;
end;
end; {ListFocusHandler}
{$IFDEF FOFF}
{$F-}
{$UNDEF FOFF}
{$ENDIF}
function LaunchList(var ListDetails: ListCfg;Tit:StrScreen; CloseProc:ListCloseProc): byte;
{}
var
WinP: WStructurePtr;
Handle: byte;
begin
WinFadeTopWin;
Listdetails.DeskListCloseCallBack := CloseProc;
if WinVars.DesktopFocusStyle <> 0 then
Listdetails.WStyle := WinVars.DesktopFocusStyle;
Handle := DisplayListEngine(Listdetails,Tit);
if Handle = 0 then
ListSetError(1004)
else
begin
WinP := WinPtr(Handle);
WinP^.ProcessKeyProc := ListProcessKeyOnDeskTop;
WinP^.CloseWinProc := ListCloseHandler;
WinP^.ChangeFocusProc := ListFocusHandler;
WinP^.UserData := @ListDetails;
end;
WinDrawTop;
LaunchList := Handle;
end; {LaunchList}
function LaunchBrowse(var ListDetails: ListCfg;Tit:StrScreen; CloseProc:ListCloseProc): byte;
{}
var
WinP: WStructurePtr;
Handle: byte;
begin
with ListDetails do
begin
if WinVars.DesktopFocusStyle <> 0 then
WStyle := WinVars.DesktopFocusStyle;
if WX1 = 0 then {user hasn't set the window}
begin
WX1 := ListVars.WX1;
WY1 := ListVars.WY1;
WX2 := ListVars.WX2;
WY2 := ListVars.WY2;
end;
Handle := BrowseCreateWin(WX1,WY1,WX2,WY2,WStyle);
if Handle = 0 then
ListSetError(1004);
end;
SetInnerDimensions(Listdetails);
ListDetails.InWindow := true;
WinFadeTopWin;
DisplayBrowseEngine(Handle,Listdetails,Tit);
Listdetails.DeskListCloseCallBack := CloseProc;
WinP := WinPtr(Handle);
WinP^.ProcessKeyProc := BrowseProcessKeyOnDeskTop;
WinP^.CloseWinProc := ListCloseHandler;
WinP^.ChangeFocusProc := ListFocusHandler;
WinP^.UserData := @ListDetails;
WinDrawTop;
LaunchBrowse := Handle;
end; {LaunchBrowse}
function LaunchBrowseFile(Fname:PathStr;Tit:StrScreen): byte;
{}
var
WinP: WStructurePtr;
Handle: byte;
BWinStyle: byte;
Result: integer;
begin
if WinVars.DesktopFocusStyle <> 0 then
BWinStyle := WinVars.DesktopFocusStyle
else
BWinStyle := ListVars.WinStyle;
WinFadeTopWin;
with ListVars do
Handle := BrowseCreateWin(WX1,WY1,WX2,WY2,BWinStyle);
if Handle = 0 then
ListSetError(1004)
else
begin
WinP := WinPtr(handle);
if GoldMaxAvail < sizeof(DeskBrowseFileInfo) then
begin
ListSetError(1004);
{no point in proceeding}
WinDispose(Handle);
LaunchBrowseFile := 0;
exit;
end;
getmem(WinP^.UserData,sizeof(DeskBrowseFileInfo));
with DeskBrowseFileInfo(WinP^.UserData^) do
begin
InitDLLStr(DataList);
DLLSetActiveList(DataList);
Result := DLLLoadFromFile(Fname);
if Result <> 0 then
begin
case Result of
1,2: ListSetError(1001);
3: ListSetError(1002);
end;
DLLDestroy;
DLLActivatePrevList;
WinDispose(Handle);
LaunchBrowseFile := 0;
exit;
end;
InitListCFG(Cfg);
ListAssignDLL(Cfg,DataList);
with CFg do
begin
WX1 := ListVars.WX1;
WY1 := ListVars.WY1;
WX2 := ListVars.WX2;
WY2 := ListVars.WY2;
WStyle := BWinStyle;
InWindow := true;
end;
SetInnerDimensions(Cfg);
end; {with}
end;
WinP := WinPtr(Handle);
DisplayBrowseEngine(Handle,DeskBrowseFileInfo(WinP^.UserData^).Cfg,Tit);
(*
DLLActivatePrevList;
*)
WinP^.ProcessKeyProc := BrowseFileProcessKeyOnDesktop;
WinP^.CloseWinProc := BrowseFileCloseHandler;
WinP^.ChangeFocusProc := ListFocusHandler;
WinDrawTop;
LaunchBrowseFile := Handle;
end; {LaunchBrowseFile}
procedure ShowList(var StrArray;StrLength:byte;TotalPicks:integer);
{Included for backward compatibility with TTT5}
var ListDetails: ListCfg;
begin
InitListCFG(Listdetails);
ListAssignArray(ListDetails,StrArray,StrLength,TotalPicks);
ListAssignArray(ListDetails, StrArray, StrLength, TotalPicks);
with Listdetails do
begin
if StrLength < ListVars.WX2 - ListVars.WX1 then
begin
WX1 := (HardVars.Width - StrLength - 2*ord(WStyle in [7,8])) div 2;
WX2 := WX1 + pred(strLength) + 2*ord(WStyle in [7,8]);
end
else
begin
WX1 := ListVars.WX1;
WX2 := ListVars.WX2;
end;
if TotalPicks < (ListVars.WY2 - ListVars.WY1 - 1) then
begin
WY1 := (HardVars.Depth - TotalPicks - 1) div 2;
WY2 := WY1 + succ(TotalPicks);
end
else
begin
WY1 := ListVars.WY1;
WY2 := ListVars.WY2;
end;
end;
RunList(Listdetails,'');
if Listdetails.LastAction = Escaped then
LPicks := 0
else
LPicks := Listdetails.ActiveNode;
end; {ShowList}
{*********************************************}
{** U N I T I N I T I A L I Z A T I O N **}
{*********************************************}
procedure ListDefaultSettings;
{}
begin
with ListVars do
begin
if ColorScreen then
begin
ListLeft := ' ';
ListRight := ' ';
end
else
begin
ListLeft := '';
ListRight := '';
end;
ListTag := '';
GridLeft := '';
GridRight := '';
GridTag := '';
ToggleKey := 32; {spacebar}
TagKey := 84; {'T'}
UnTagKey := 85; {'U'}
TagAllKey := 20; {Ctrl-T}
UnTagAllKey := 21;{Ctrl-U}
WinStyle := 7;
WX1 := 10; {default window coordinates}
WX2 := 70;
WY1 := 2;
WY2 := 24;
WrapWinType := WStretch;
LastActiveItem := 0;
EMsgFunc := ListEMsg;
end;
end; { ListDefaultSettings }
procedure GoldListInit;
{}
begin
ListDefaultSettings;
end; {GoldListInit}
{$IFDEF TTT5}
procedure Default_Settings;
{}
begin
{abstract}
end; { Default_Settings }
procedure Show_List(var StrArray;StrLength:Byte;TotalPicks:byte);
{}
begin
ShowList(StrArray,StrLength,TotalPicks);
end; { Show_List }
procedure New_Show_List(var StrArray;StrLength:Byte;TotalPicks:byte);
{}
begin
ShowList(StrArray,StrLength,TotalPicks);
end; { New_Show_List }
{$ENDIF}
begin
GoldListInit;
end.